var fs = require("jsdoc/fs");
var helper = require("jsdoc/util/templateHelper");
var path = require("jsdoc/path");
var htmlsafe = helper.htmlsafe;


/**
 * 获取指定目录下的所有glsl文件内容，提取方法和uniform对象
 * @param {string} dirPath glsl文件所在目录路径
 * @param {string} imgDir glsl文件对应文件所在的目录
 * @returns {Array} 包含方法和uniform的数组
 */
function getGlslContent(dirPath, imgDir) {
  const fs = require('jsdoc/fs');
  const path = require('path');

  let results = [];

  // 递归遍历目录获取所有.glsl文件
  function walkDir(dir) {
    const files = fs.readdirSync(dir);
    files.forEach(file => {
      const filePath = path.join(dir, file);
      const stat = fs.statSync(filePath);
      if (stat.isDirectory()) {
        walkDir(filePath);
      } else if (file.endsWith('.glsl')) {
        getGLSLContent(filePath, results, dirPath);
      }
    });
  }

  let imgFilesRes = [];
  const imgFiles = fs.readdirSync(imgDir).filter(file => fs.statSync(path.join(imgDir, file)).isFile());
  imgFiles.forEach(file => {
    imgFilesRes.push(file);
  });

  walkDir(dirPath);
  return {
    results: results,
    imgFiles: imgFilesRes
  };
}
/**
 * 
 * @param {string} filePath  要求读取的文件
 */
function getGLSLContent(filePath, results, dirPath) {
  const fs = require('jsdoc/fs');

  // 读取glsl文件内容
  let content = fs.readFileSync(filePath, 'utf-8');

  // 提取其中的shadertoycode
  const shadertoyCodeMatches = content.match(/\/\/shadertoycode[\s\S]*?\/\/shadertoycode/g) || [];
  shadertoyCodeMatches.forEach(codeBlock => {
    results.push({
      type: 'shadertoycode',
      content: codeBlock,
      filename: filePath.substring(dirPath.length + 1)
    });
  });

  // 如果提取到shadertoyCodeMatches，那么content内容就需要删除这部分文字
  if (shadertoyCodeMatches.length > 0) {
    content = content.replace(/\/\/shadertoycode[\s\S]*?\/\/shadertoycode/g, '');
  }


  // 提取方法和注释
  // Match functions with or without comments
  const functionMatches = content.match(/(?:\/\*\*[\s\S]*?\*\/\s*)?(vec2|float|vec3|vec4|void|mat3|mat4|bool|czm_material)\s+[\w]+\s*\([^)]*\)/g) || [];

  functionMatches.forEach(match => {
    // Extract comment if it exists
    const commentMatch = match.match(/\/\*\*([\s\S]*?)\*\//);

    // Extract function name
    const funcNameMatch = match.match(/(vec2|float|vec3|vec4|void|mat3|mat4|bool|czm_material)\s+([\w]+)/);
    const functionName = funcNameMatch ? funcNameMatch[2] : '';

    results.push({
      type: 'function',
      name: functionName,
      comment: commentMatch && commentMatch.length > 1 ? commentMatch[1].trim() : '', // Use capture group 1 to get just comment content
      content: match,
      filename: filePath.substring(dirPath.length + 1)
    });
  });

  // 提取uniform对象
  const uniformMatches = content.match(/uniform\s+[\w\s\[\]]+\s+\w+;/g) || [];
  uniformMatches.forEach(match => {
    results.push({
      type: 'uniform',
      name: match.match(/uniform\s+[\w\s\[\]]+\s+\w+;/g)[0].match(/uniform\s+[\w\s\[\]]+\s+\w+;/g)[0],
      content: match,
      filename: filePath.substring(dirPath.length + 1)
    });
  });
}

// Generate HTML files for GLSL documentation
/** */
function generateGlslDocs(glslAndImgs, view) {
  const { results, imgFiles } = glslAndImgs;

  const fs = require('jsdoc/fs');
  const path = require('path');

  if (!results || !results.length) return;

  const outDir = "Build/Documentation/glsl";
  fs.mkdirSync(outDir, { recursive: true });

  // Group results by filename
  const fileGroups = {};
  results.forEach(result => {
    if (!fileGroups[result.filename]) {
      fileGroups[result.filename] = [];
    }
    fileGroups[result.filename].push(result);
  });

  generateGlslIndexFile(fileGroups, outDir);

  // Generate one HTML file per source file
  Object.entries(fileGroups).forEach(([filename, fileResults]) => {

    let html = '<div class="container-overview">';


    let filenameDepth = filename.split('\\');
    const imgFileName = filenameDepth[filenameDepth.length - 1].replace('.glsl', '.');
    const matchingImgFiles = imgFiles.filter(img => img.startsWith(imgFileName));

    if (matchingImgFiles.length > 0) {
      matchingImgFiles.forEach(imgFile => {
        html += `<div class="img-container" style="text-align: center;">
                <img src="../Docs/imgs/Shaders/${imgFile}" style="max-height: 600px;width: 500px;padding-top:30px;" alt="${imgFileName} image">
            </div>`;
      });
    }

    fileResults.forEach(result => {
      if (result.type === 'function') {
        html += `<div class="details">
            <div class="method-details">
              <h3 class="method-title"><i class="fas fa-code"></i> ${result.name}</h3>
              <div class="description">
                <div class="method-content">
                  <pre class="prettyprint source"><code>${htmlsafe(result.content)}</code></pre>
                </div>
              </div>
            </div>
          </div>`;
      } else if (result.type === 'uniform') {
        html += `<div class="details">
            <div class="uniform-details">
              <h3 class="uniform-title"><i class="fas fa-cog"></i> Uniform Declaration</h3>
              <div class="description">
                <div class="uniform-content">
                  <pre class="prettyprint source"><code>${htmlsafe(result.name)}</code></pre>
                </div>
              </div>
            </div>
          </div>`;
      } else if (result.type === 'shadertoycode') {
        html += `<div class="details">
            <div class="shadertoy-details">
              <h3 class="shadertoy-title"><i class="fas fa-paint-brush"></i> ShaderToy Code</h3>
              <div class="description">
                <button onclick="navigator.clipboard.writeText(\`${htmlsafe(result.content)}\`)">Copy Code to Clipboard</button>
                <button onclick="window.open('https://www.shadertoy.com/new', '_blank')">Open ShaderToy</button>
                <div class="shadertoy-content">
                  <pre class="prettyprint source"><code>${htmlsafe(result.content)}</code></pre>
                </div>
              </div>
            </div>
          </div>`;
      }
    });

    html += '</div>';

    const outFilename = filename.replace('.glsl', '').replace(/[^a-z0-9]/gi, '_').toLowerCase();
    const outpath = path.join(outDir, outFilename + '.html');

    const fullHtml = `<!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="utf-8">
          <title>${filename}</title>
          <link type="text/css" rel="stylesheet" href="../styles/jsdoc-default.css">
          <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
      </head>
      <body>
          <div id="main">
              <h1 class="page-title">${filename}</h1>
              ${html}
          </div>
      </body>
      </html>`;

    fs.writeFileSync(outpath, fullHtml, "utf8");
  });
}
/*
<details level-tag="0">
    <summary class="tree-item">Beidou</summary>
    <li data-name="BeidouBoundingBox">
      <details>
          <summary class="tree-item">
              <i class="ag">AG</i>
              <i class="developLevel">2</i>
              <a href="BeidouBoundingBox.html">BeidouBoundingBox</a>
          </summary>
       </details>
    </li>
    <li data-name="BeidouGridCell">
      <details>
        <summary class="tree-item">
          <i class="ag">AG</i>
          <i class="developLevel">3</i>
          <a href="BeidouGridCell.html">BeidouGridCell</a>
        </summary>
      </details>
    </li>
</details>
 */

function generateGlslIndexFile(fileGroups, outDir) {
  // Generate index file for GLSL docs
  let indexHtml = `<!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="utf-8">
      <title>GLSL Documentation</title>
      <link type="text/css" rel="stylesheet" href="../styles/jsdoc-default.css">
      <link href="styles/prism.css" rel="stylesheet">
      <style>
        .container {
          display: flex;
          height: 100vh;
        }
        
        .content {
          flex: 1;
          height: 100%;
        }
        iframe {
          width: 100%;
          height: 100%;
          border: none;
        }
      </style>
    </head>
    <body>
      <div class="container">
          <h2>GLSL Files</h2>
          <div class="nav">
            <div class="menu">
              <div id="ClassList" class="ClassList">
                <div id="tree" class="tree">`;

  // Build tree structure
  const tree = {};
  Object.keys(fileGroups).forEach(filename => {
    const parts = filename.split('\\');
    let current = tree;
    for (let i = 0; i < parts.length; i++) {
      const part = parts[i];
      if (i === parts.length - 1) {
        // File node
        current[part] = {
          isFile: true,
          filename: filename,
          path: parts.slice(0, i).join('\\')
        };
      } else {
        // Directory node
        if (!current[part]) {
          current[part] = {
            isDirectory: true,
            path: parts.slice(0, i + 1).join('\\'),
            children: {}
          };
        }
        current = current[part].children;
      }
    }
  });

  function generateTreeHtml(node, path = '') {
    let html = '';
    Object.keys(node).sort((a, b) => {
      // Directories come first
      const aIsDir = node[a].isDirectory;
      const bIsDir = node[b].isDirectory;
      if (aIsDir && !bIsDir) return -1;
      if (!aIsDir && bIsDir) return 1;
      return a.localeCompare(b);
    }).forEach(key => {
      const item = node[key];
      if (item.isFile) {
        const safeFilename = item.filename.replace('.glsl', '').replace(/[^a-z0-9]/gi, '_').toLowerCase();
        html += `
            <li data-name="${safeFilename}">
              <details>
                <summary class="tree-item">
                  <i class="ag">AG</i>
                  <i class="developLevel">3</i>
                  <a class="tree-item" onclick="document.getElementById('content-frame').src='${safeFilename}.html'">${key}</a>
                </summary>
              </details>
            </li>`;
      } else {
        html += `
             <details level-tag="0">
              <summary class="tree-item">${key}</summary>
               ${generateTreeHtml(item.children, item.path)}
              </details>`;
      }
    });
    return html;
  }

  indexHtml += generateTreeHtml(tree);

  indexHtml += `
                </div>
              </div>
          </div>
        </div>
        <div class="content">
          <iframe id="content-frame"></iframe>
        </div>
      </div>
      <script>
        document.querySelectorAll('.tree-folder').forEach(folder => {
          folder.addEventListener('click', (e) => {
            if(e.target === folder) {
              folder.classList.toggle('open');
            }
          });
        });
      </script>
      <script src="javascript/contentList.js"></script>
    </body>
    </html>`;

  fs.writeFileSync(path.join(outDir, 'index.html'), indexHtml);
}

module.exports = {
  getGlslContent,
  generateGlslDocs,
  generateGlslIndexFile
};